﻿using AutoMapper;
using HamcoWcs.Contract;
using HamcoWcs.Contract.ContractCommon;
using HamcoWcs.Contract.ContractMainTask;
using HamcoWcs.Contract.ContractMes;
using HamcoWcs.Contract.ContractPcon;
using HamcoWcs.Contract.MachineStatus;
using HamcoWcs.DAL;
using HamcoWcs.Entitys.BaseConfigs;
using HamcoWcs.Entitys.DeviceErrors;
using HamcoWcs.Entitys.Logs;
using HamcoWcs.Models.Common;
using HamcoWcs.Models.Common.Enums;
using HamcoWcs.Models.DeviceMsgs;
using HamcoWcs.Models.Devices;
using HamcoWcs.Models.Events;
using HamcoWcs.Models.TibcoMessage;
using HamcoWcs.Service.Common;
using NPOI.SS.Formula.Functions;
using Quartz.Impl.Triggers;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading;

namespace HamcoWcs.Service.Pcon
{
    [AutoInject(typeof(IPconStateService), InjectType.Scope)]
    public class PconStateService : ScopeServiceBase, IPconStateService
    {
        public void PconStateChangedReport(PconDto con, PconRecvMsg msg)
        {
            try
            {
                WharfDeviceHandle(con, msg); // 码头设备状态变更处理
                InPortDeviceHandle(con, msg); // 2F实栈板投入到货架
                OutPortDeviceHandle(con, msg);// 排出到2F产线或清洗设备
                NormalReporthandle(con, msg); // 通常情况上报PalletLocationChange

                UpdateMachineState(con);// 上报设备状态
                UpdarePortState(con, msg);
                ErrorHandel(con, msg);
                con.Machine.StatusChangeEvent -= OnPconStateChangeHandle;
            }
            catch (Exception ex)
            {
                con.Machine.StatusChangeEvent -= OnPconStateChangeHandle;
                _logger.AddSystemErrorLog($"PconStateService->PconStateChangedReport:" + ex.Message);
            }
        }

        private void UpdarePortState(PconDto con, PconRecvMsg msg)
        {
            if (con.MachineName.Contains("CJVCV")) return;
            if (con.MachineName.Contains("CJMIF")) return;
            if (con.MachineName.Contains("CJMCV") && con.PortName != "01") return;

            _mesCommunicateService.PortStateChanged(con, msg);
        }

        private void NormalReporthandle(PconDto con, PconRecvMsg msg)
        {
            if (con.MachineName == "CJMCV300" || con.MachineName == "CJMCV700")
            {
                return;
            }
            //if (con.PconType != EnumPconType.NormalReport) return;
            PalletLocationChange(con, msg);
        }


        /// <summary>
        /// 上报位置变更（有任务的情况）
        /// </summary>
        private void PalletLocationChange(PconDto con, PconRecvMsg msg)
        {
            if (con.IsGoods == 0 && msg.IsGoods == 1)
            {
                string palletName = msg.UnitId;
                if (string.IsNullOrEmpty(palletName)) return;

                var task = _wcsDbContext.MainTasks.Where(x => x.UnitId == palletName).FirstOrDefault();
                //var task = _mainTaskService.GetCurrentMainTaskByPallet(palletName);
                if (task == null)
                {
                    _mesCommunicateService.PalletLocationChangedReport(new PalletLocationChangedReportMessage(new PalletLocationChangedReportMessageBody(con.MachineName, con.PortName, msg.UnitId, "IN")));
                }
                else
                {
                    _mesCommunicateService.PalletLocationChanged(new PalletLocationChangedMessage(new PalletLocationChangedMessageBody()
                    {
                        CurrentMachineName = con.MachineName,
                        CurrentPositionName = con.PortName,
                        CurrentPositionType = "PORT",
                        CurrentZoneName = "",
                        EventUser = con.MachineName,
                        PalletName = palletName,
                        TransportJobName = task.TaskId,
                        TransferState = "MOVING"
                    }));
                }

            }
        }

        private AlarmExplanation GetAlarm(string errorCode)
        => _wcsDbContext.AlarmExplanations
                    .Where(x => x.Module == "pcon")
                    .Where(x => x.Code == errorCode)
                    .FirstOrDefault() ?? new AlarmExplanation()
                    {
                        AlarmName = "未知异常",
                        Code = errorCode,
                        ErrorType = "UnKnown",
                        Level = -1,
                        Module = "UnKnown",
                        Suggestion = "UnKnown",
                        Summary = "UnKnown",
                    };

        private void ErrorHandel(PconDto con, PconRecvMsg msg)
        {
            //安全异常另外统计
            if (con.ErrorCode == 1) return;

            // 触发异常
            if (msg.PconMode == 4 && con.PconMode != 4)
            {
                var a = _wcsDbContext.DeviceErrorQueues.Any(x => x.MachineName == con.MachineName && x.PortName == con.PortName);
                if (a) return;

                var errorCode = msg.ErrorCode.ToString();

                var alarm = GetAlarm(errorCode);
                if (string.IsNullOrEmpty(alarm.AlarmName)) return;

                var d = new DeviceErrorQueue()
                {
                    CreatedTime = DateTime.Now,
                    ErrorCode = errorCode,
                    ErrorDetail = alarm.AlarmName,
                    ErrorLevel = alarm.Level.ToString(),
                    LastUpdateTime = DateTime.Now,
                    MachineName = con.MachineName,
                    PortName = con.PortName,
                    PlcName = con.PlcName
                };

                if (d.ErrorDetail == "安全异常")
                {
                    return;
                }

                _wcsDbContext.DeviceErrorQueues.Add(d);
                _wcsDbContext.SaveChanges();
                _mesCommunicateService.AlarmReportSet(d);
            }
            // 解除异常
            else if (msg.PconMode != 4 && con.PconMode == 4 || msg.PconMode != 4 && con.PconMode != 4)
            {
                con.AlarmTick = 0;
                var d = _wcsDbContext.DeviceErrorQueues.FirstOrDefault(x => x.MachineName == con.MachineName && x.PortName == con.PortName);

                if (d is null) return;


                d.LastUpdateTime = DateTime.Now;

                var duration = (d.LastUpdateTime - d.CreatedTime);
                if (duration.TotalSeconds > 5)
                {
                    var l = new DeviceErrorLog()
                    {
                        SetTime = duration.GetDuration(),
                        CreatedTime = d.CreatedTime,
                        LastUpdateTime = d.LastUpdateTime,
                        DeviceName = con.DeviceName,
                        ErrorCode = d.ErrorCode,
                        ErrorDetail = d.ErrorDetail,
                        PlcName = con.PlcName,
                    };
                    _wcsDbContext.DeviceErrorLogs.Add(l);
                }

                _wcsDbContext.Remove(d);
                _wcsDbContext.SaveChanges();
                _mesCommunicateService.AlarmReportClear(d);
            }
            else
            {
                con.AlarmTick = 0;
            }
        }


        // 码头事件
        public void WharfDeviceHandle(PconDto con, PconRecvMsg msg)
        {
            if (!(con.PconType == EnumPconType.Wharf
                || con.PconType == EnumPconType.Wharf1)) return;

            if (con.PconType == EnumPconType.Wharf)
            {
                // 方向切换报告
                //WorkTypeDiff(con, msg);
                // 入库模式 搬出上报UC
                if (con.WorkType == 1 && msg.WorkType == 1 && con.IsGoods == 1 && msg.IsGoods == 0)
                {
                    con.PortState = "UC";
                    _mesCommunicateService.PortTransferStateChanged(con);
                }

                // 出库模式
                if (con.WorkType == 2 && msg.WorkType == 2)
                {
                    if (con.IsGoods == 0 && msg.IsGoods == 0 && (string.IsNullOrEmpty(con.PortState)))
                    {
                        con.PortState = "LR";
                        _mesCommunicateService.PortTransferStateChanged(con);
                    }

                    if (con.IsGoods == 1 && msg.IsGoods == 0)
                    {
                        con.PortState = "LR";
                        _mesCommunicateService.PortTransferStateChanged(con);
                    }

                    if (con.IsGoods == 0 && msg.IsGoods == 1)
                    {
                        con.PortState = "LC";
                        _mesCommunicateService.PortTransferStateChanged(con);
                    }
                }
            }
            /*
            //if (con.WorkType == 2 && msg.WorkType == 2 && con.PconType == EnumPconType.Wharf1)
            //{
            //    // 搬出
            //    if (con.IsGoods == 1 && msg.IsGoods == 0)
            //    {
            //        _mesCommunicateService.PalletLocationChangedReport(new PalletLocationChangedReportMessage(new PalletLocationChangedReportMessageBody(con.MachineName, con.PortName, con.UnitId, "OUT")));

            //    }

            //    // 搬入
            //    if (con.IsGoods == 0 && msg.IsGoods == 1)
            //    {
            //        _mesCommunicateService.PalletLocationChangedReport(new PalletLocationChangedReportMessage(new PalletLocationChangedReportMessageBody(con.MachineName, con.PortName, msg.UnitId, "IN")));
            //    }
            //}
            */

        }

        /// <summary>实栈板投料事件</summary>
        public void InPortDeviceHandle(PconDto con, PconRecvMsg msg)
        {
            // 实栈板入库交互点
            if (con.PconType != EnumPconType.InPortInteractive) return;

            if (con.IsGoods == 1 && msg.IsGoods == 0)
            {
                Thread.Sleep(1);
                con.PortState = "UC";
                _mesCommunicateService.PortTransferStateChanged(con);
            }
        }



        // 货架出库到清洗机或产线
        public void OutPortDeviceHandle(PconDto con, PconRecvMsg msg)
        {
        }


        public void UpdateMachineState(PconDto pcon)
        {
            try
            {
                pcon.Machine.StatusChangeEvent += OnPconStateChangeHandle;
                if (pcon.Machine.UpdateControlState())
                {
                    _mesCommunicateService.MachineControlStateChanged(pcon.Machine);
                }

                if (pcon.Machine.UpdateState())
                {
                    if (pcon.PconMode == 4)
                    {
                        _mesCommunicateService.MachineStateChanged(pcon);
                    }
                    else
                    {
                        _mesCommunicateService.MachineStateChanged(pcon.Machine);
                    }
                }

                pcon.Machine.UpdatePconState();

            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally 
            {
                pcon.Machine.StatusChangeEvent -= OnPconStateChangeHandle;
            }
           
            
            //_mesCommunicateService.PortStateChanged(new PortStateChangedMessage(new PortStateChangedMessageBody(pcon.MachineName, pcon.PortName, portState)));
            //}

        }

        private void OnPconStateChangeHandle(object sender, StateChangeEvent e)
        {
            _machineStateService.SaveMachineState(e.MachineName, e.MachineState);
        }
        #region Constructor

        private readonly IMesCommunicateService _mesCommunicateService;
        private readonly ILoggerService _logger;
        private readonly IBaseMainTaskService _mainTaskService;
        private readonly IMachineStateService _machineStateService;

        public PconStateService(WcsDbContext wcsDbContext, IMapper mapper, IMesCommunicateService mesCommunicateService, ILoggerService logger, IBaseMainTaskService mainTaskService,IMachineStateService machineStateService)
            : base(wcsDbContext, mapper)
        {
            _logger = logger;
            _mesCommunicateService = mesCommunicateService;
            _mainTaskService = mainTaskService;
            _machineStateService = machineStateService;
        }

        #endregion
    }
}
